perm filename RSEXEC.MID[NET,MRC]1 blob sn#343821 filedate 1978-03-21 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00018 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	TITLE RSEXEC
C00005 00003	Data area
C00008 00004	Interrupt server
C00010 00005	Start of program
C00013 00006	ICP ICP ICP
C00015 00007	Main program loop
C00018 00008	 TTY input interrupt
C00022 00009	 Network input interrupt
C00025 00010	Command dispatch
C00027 00011	Command service routines
C00028 00012	 More commands
C00030 00013	Append file
C00033 00014	Output file
C00035 00015	Input file
C00037 00016	DDT bopper
C00038 00017	Filespec input
C00041 00018	Sixbit & numeric TTY I/O
C00043 ENDMK
C⊗;
TITLE RSEXEC
SUBTTL Definitions

; Mark Crispin, SU-AI, March 1978

; Assembly switches

IFNDEF RSXSKT,NPRSKT==367		; ICP socket
IFNDEF PDLLEN,PDLLEN==50.		; PDL length
IFNDEF TTOBFL,TTOBFL==50.		; TTY output buffer length
IFNDEF CLKSPD,CLKSPD==2.		; number of seconds between clock ints

;  AC definitions.  0→3 are used by NETWRK.
; 0 is also used as very temp in the main program.
; X, Y, Z, A, and B are in approximate descending order of usage.

X=4 ? Y=5 ? Z=6 ? A=7 ? B=10 ? P=17

; I/O channels.  NETWRK uses 0 and 1.

DSI==2 ? DSO==3

; Macro to send a TELNET command

DEFINE TELCMD CMDLST
 SKIPE DEBUGP
  OUTSTR [ASCIZ/⊗!CMDLST!*
/]
 IRPS CMD,,CMDLST
  MOVEI CMD
  PUSHJ P,NETOCH
 TERMIN
 PUSHJ P,NETSND
TERMIN

; SAIL system bit definitions

INTTTY==020000,,			; TTY input interrupt
INTCLK==000200,,			; clock interrupt
DISLIN==400000,,			; III
DMLIN== 040000,,			; DM
DDDLIN==020000,,			; DD
PTYLIN==004000,,			; PTY
IMPBIT==001000,,			; IMP TTY
SPCBRK==000100,,			; special activation mode
BSACT== 000020				; activate on backspace

; Include wonderful network routines

NIORTS==-1				; include I/O routines
ERRHAN==-1				; include automagic error handling
ERRINS==IF1,[0] .ELSE JRST CONERR	; error instruction
ERRTNS==-1				; include error routines

.INSRT NETWRK[NET,MRC]
SUBTTL Data area

CORBEG==.

FSPBLK:	BLOCK 4				; filespec block
INPFLN:	BLOCK 1				; input filename stuff
INPEXT:	BLOCK 1
INPPPN:	BLOCK 1
OUTFLN:	BLOCK 1				; output filename stuff
OUTEXT:	BLOCK 1
OUTPPN:	BLOCK 1

; Flags

TTINTP:	BLOCK 1				; -1 → TTI interrupt
NTINTP:	BLOCK 1				; -1 → NTI interrupt
NTOINP:	BLOCK 1				; ≤ -1 → output should be flushed
CLSINP:	BLOCK 1				; -1 → connection closing
ISLURP:	BLOCK 1				; -1 → in input slurping mode
NTBFOP:	BLOCK 1				; -1 → something in net buffer
INPFLP:	BLOCK 1				; -1 → input file opened
SLOWFP:	BLOCK 1				; -1 → input in slow mode
OUTFLP:	BLOCK 1				; -1 → output file opened
CHARMP:	BLOCK 1				; -1 → in character mode
TRANSP:	BLOCK 1				; -1 → transparent mode


; Connection option flags

ECHOP:	BLOCK 1				; -1 → remote echoing

; Buffer headers

DSIBF:	BLOCK 3				; disk input buffer
DSOBF:	BLOCK 3				; disk output buffer

; TTY buffer stuff

TTOBFR:	BLOCK TTOBFL			; TTY output buffer
TTOCTR:	BLOCK 1				; TTY output counter
TTOPTR:	BLOCK 1				; TTY output pointer

COREND==.-1

; Stuff set in once only code and protected for restart zapping.

; Other buffers

PDL:	BLOCK PDLLEN			; pushdown list

; Other flags

DEBUGP:	BLOCK 1				; -1 → MRC is fooling around
DPYP:	BLOCK 1				; -1 → display terminal
DMDPYP:	BLOCK 1				; -1 → DM display

ESCHAR:	↑↑				; escape character for printing consoles
SUBTTL Interrupt server

;  Interrupts only set flags which the main program (normally in INTW⊗
; state) looks at.  Clock interrupts fake the world since it is possible
; to lose an interrupt otherwise.

INTSER:	SKIPN X,JOBCNI			; get interrupt status
	 FATAL Null interrupt
	TLNE X,(INTCLK)			; clock int fakes TTI and NTI
	 TLO X,(INTTTY\INTINP)
	TLNE X,(INTTTY)			; TTI int
	 SETOM TTINTP
	TLNE X,(INTINP)			; NTI int
	 SETOM NTINTP
	TLNE X,(INTIMS)			; status change
	 SETOM CLSINP
	TLNN X,(INTINR)
	 JRST INTSR1
	SKIPE DEBUGP
	 OUTSTR [ASCIZ/*INR*
/]
	DISMIS
INTSR1:	TLNN X,(INTINS)			; IMP INS int
	 DISMIS
	SOSL NTOINP
	 JRST INTSR2			; dismiss interrupt

; Network interrupt, abort all TTY output!

	MOVEI X,5*TTOBFL-1		; reset TTY buffer counter
	MOVEM X,TTOCTR
	MOVE X,[440700,,TTOBFR]		; reset TTY buffer pointer
	MOVEM X,TTOPTR
	SETZM X,TTOBFR			; and zap buffer while at it
	MOVE X,[TTOBFR,,TTOBFR+1]
	BLT X,TTOBFR+TTOBFL-1
INTSR2:	SKIPE DEBUGP
	 OUTSTR [ASCIZ/*INS*
/]
	DISMIS				; dismiss interrupt
SUBTTL Start of program

RSEXEC:	JFCL
	RESET

; Paw over terminal characteristics

CHKTTY:	SETZM DPYP ? SETZM DMDPYP
	HRROI [003000,,]
	TTYSET				; get line characteristics
	CAMN [-1]
	 EXIT				; how can I work if detached?
	TLNE (DISLIN\DMLIN\DDDLIN)	; display?
	 SETOM DPYP
	TLNE (DMLIN)			; DM?
	 SETOM DMDPYP

; Check for net-hoppers.

	TLNN (IMPBIT)			; check for net hoppers
	 JRST NOTHOP

; This loser is net hopping!

NETHOP:	GETPPN
	 JFCL
	HRRZS
	CAIN 'MRC
	 JRST NOTHOP
	OUTSTR [ASCIZ/Foo you are a net hopper.

 You are logged into SAIL over the ARPAnet.  It is a waste of SAIL's
limited system resources (jobs, network links, etc.) to go back again
over the same network.  It also greatly slows down response to you
and increases the chances of lossage due to a system or network failure.

 You should not do this unless you have a good reason to do so.  If you
have any questions, please contact MRC and LES for more information.
Thank you for your co-operation.

 Are you SURE you want to TELNET now?/]
	INCHRW
	ANDI 137
	CAIE "Y
	 EXIT
	OUTSTR [ASCIZ/
/]

; Set up the world

NOTHOP:	RESET				; clear all I/O
	MOVE JOBFF
	CORE				; smallify
	 JFCL
	SETZM CORBEG
	MOVE [CORBEG,,CORBEG+1]
	BLT COREND			; zak!
	MOVE P,[PDL(-PDLLEN)]		; set up stack pointer
	OPEN DSI,[0 ? 'DSK,, ? DSIBF]	; get a disk input channel
	 FATAL DSK OPEN failed
	OPEN DSO,[0 ? 'DSK,, ? DSOBF,,]	; get a disk output channel
	 FATAL DSK OPEN failed
	SETACT [[	777777,,777777	; activate on everything
			777777,,777777	; just set it up for when we need it
			777777,,777777
			777777,,600000\BSACT]]
	MOVEI 126 ? MOVEM HOST		; USC-ISI
	MOVEI 367 ? MOVEM ICPSKT	; TIPSER

; (continued on next page)
SUBTTL ICP ICP ICP

	PTJOBX [0 ? 3]			; local echo off
	OUTSTR [ASCIZ/ Trying... /]
	PUSHJ P,CONECT			; call wonderful ICPer
	OUTSTR [ASCIZ/Open
/]

; Initialize interrupts

	MOVEI INTSER
	MOVEM JOBAPR			; set up interrupt server
	CLKINT 60.*CLKSPD		; start the ticking clock
	MOVSI (INTTTY\INTCLK\INTINS\INTINR\INTIMS\INTINP)
	INTENB				; enable interrupts

; Random other initialization

	LOCK				; prevent swapouts
	SKIPN DPYP
	 PUSHJ P,ETRANS			; enter transparent mode
	SNEAKS
	 JRST GOICP1
	CAIN 700			; if αβ@ typed ahead
	 SETOM DEBUGP			; MRC is fooling around!

; Initialize TTY output buffer variables and randomness

GOICP1:	MOVEI 5*TTOBFL-1		; set up TTY buffer counter
	MOVEM TTOCTR
	MOVE [440700,,TTOBFR]		; set up TTY buffer pointer
	MOVEM TTOPTR
	SETZM TTOBFR
	MOVE [TTOBFR,,TTOBFR+1]
	BLT TTOBFR+TTOBFL-1
	INSKIP
	 JRST SLEEPR
	SETOM TTINTP

; (continued on next page)
SUBTTL Main program loop

SLEEPR:	SKIPL INPFLP			; unless input file open,
	 IWAIT				; sleep for an interrupt
SLEPR1:	AOSG TTINTP			; TTY int?
	 JRST TTISER
	SKIPN CLSINP			; if closing, keep trying input till lossage
	 AOSG NTINTP			; NTI int?
	  JRST NTISER
	SKIPL INPFLP			; input file open?
	 JRST SLEEPR
GETDCH:	SOSG DSIBF+2
	 IN DSI,
	  CAIA
	   JRST [	CLOSE DSI,
			PUSHJ P,NETSND
			OUTSTR [ASCIZ/End of input file /]
			MOVE X,INPFLN
			PUSHJ P,OUTSIX
			OUTCHR [".]
			MOVE X,INPEXT
			PUSHJ P,OUTSIX
			OUTCHR ["[]	;]
			HLLZ X,INPPPN
			PUSHJ P,OUTSIX
			OUTCHR [",]
			HRLZ X,INPPPN
			PUSHJ P,OUTSIX
			OUTSTR [ASCIZ/].
/]
			SETZM INPFLP
			JRST SLEEPR]
	ILDB DSIBF+1
	JUMPE GETDCH
	SKIPE SLOWFP			; nice slow file processing?
	 JRST CHRHAK			; yah, force on every character

; Duplicate of TTYSER's CHRHAK to avoid a force on each character

	SKIPN ECHOP			; echo if in local mode
	 OUTCHR				; (this way avoids command echoing)

; Canonicalize from SAIL to standard ASCII

	CAIN 175			; ALT
	 MOVEI 33
	CAIN 176			; }
	 MOVEI 175
	CAIN 32				; ~
	 MOVEI 176

; Here to actually send the character

	PUSHJ P,NETOCH			; output the character
	JRST SLEPR1

; Here if connection is losing

CONERR:	SKIPE CLSINP			; not closing?
	 SKIPE ISLURP			; error in slurping?
	  JRST PUNT
	JRST NTISER			; no, start slurping
; TTY input interrupt

TTISER:	INCHSL				; get a character
	 JRST [	AOSG NTBFOP		; anything in the buffer?
		 PUSHJ P,NETSND		; force it out
		AOSG NTINTP		; TTI buffer empty
		 JRST NTISER		; but some net stuff to handle
		JRST SLEEPR]

;  Command and mapping stuff.  We only map between our character set and
; ASCII.  Anybody who wants mapping to MIT's character set should use SUPDUP!!

	SKIPE TRANSP			; ↑↑ processing if transparent
	 JRST [	TRZ 600			; zap crud bit
		CAIN ↑M
		 JRST [	PUSHJ P,NETOCH	; ↑M must have ↑J afterwards
			MOVEI ↑J	; but image mode suppresses the
			JRST CHRHAK]	; system doing it for us
		CAME ESCHAR
		 JRST CHRHAK		; not escape character
		INCHRW
		ANDI 177		; turn off parity and crud
		CAMN ESCHAR		; escape quotes itself
		 JRST CHRHAK
		CAIN "-			; command off?
		 JRST [	INCHRW
			IORI 600	; form αβcharacter
			JRST .+1]
		IORI 400		; form αcharacter
		JRST .+1]
	CAIN 775			; αβALT is magic
	 PUSHJ P,DDTCAL
	CAIN 777			; αβBS?
	 JRST [	MOVEI 177 ? JRST TTISR1]; just an ordinary character
	TRZE 400			; META set?
	 JRST [	LDB X,[000700,,0]	; get ASCII part
		CAILE X,"←
		 SUBI X,"a-"A		; uppercaseify if necessary
		SUBI X,"@
		JUMPL X,NTISER		; no op character
		TRNN 200		; CONTROL?
		 SKIPA X,CMCDSP(X)	; no, use right half
		  HLR X,CMCDSP(X)	; yes, use left half
		PUSHJ P,(X)
		JRST TTISER]
	TRZE 200			; if CONTROL is set
	 JRST [	TRZ 140			; convert to canonical ASCII control
		JRST TTISR1]

; Here only if an ASCII printing character

CHRHAK:	SKIPN ECHOP			; echo if in local mode
	 OUTCHR				; (this way avoids command echoing)

; Canonicalize from SAIL to standard ASCII

	SKIPE TRANSP			; no canonicalization need if transparent
	 JRST TTISR1
	CAIN 175			; ALT
	 MOVEI 33
	CAIN 176			; }
	 MOVEI 175
	CAIN 32				; ~
	 MOVEI 176

; Here to actually send the character

TTISR1:	PUSHJ P,NETOCH			; output the character
	SETOM NTBFOP			; flag there is network output
	JRST TTISER
; Network input interrupt

NTISER:	SKIPE CLSINP			; closing?
	 JRST [	SKIPN ISLURP		; in slurp mode?
		 JSP X,[SETOM ISLURP	; tell CONERR we are slurping
			OUTSTR TTOBFR	; output what was in buffer first
			JRST (X)]
		PUSHJ P,NETICW		; slurp slurp slurp
		JRST NTISR2]
	AOSG TTINTP
	 JRST [	SETOM NTINTP		; make sure we come back here
		JRST TTISER]		; give the TTY a chance!
	PUSHJ P,NETICH			; get a character
	 JRST [	OUTSTR TTOBFR
		MOVEI 5*TTOBFL-1	; reset TTY buffer counter
		MOVEM TTOCTR
		MOVE [440700,,TTOBFR]	; reset TTY buffer pointer
		MOVEM TTOPTR
		SETZM TTOBFR
		MOVE [TTOBFR,,TTOBFR+1]
		BLT TTOBFR+TTOBFL-1
		AOSG TTINTP
		 JRST TTISER		; TTI int to be taken care of
		JRST SLEEPR]		; else sleep
NTISR2:	TRNE 200			; command?
	 JRST [	CAIN 200 ? AOS NTOINP
		CAIN 203 ? SETOM ECHOP
		CAIN 204 ? SETZM ECHOP
		JRST NTISER]
NTISR1:	SKIPE TRANSP			; no canonicalization needed if transparent
	 JRST NTIS1A
	JUMPE NTISER			; flush nulls
	CAIN 176			; ~
	 MOVEI 32
	CAIN 175			; }
	 MOVEI 176
	CAIN 33				; diamond
	 MOVEI 175
	CAIN ↑G
	 JRST [	HRROI -1
		BEEP
		JRST NTISER]		; map bells to bells
	CAIN 177			; rubout is usually padding
	 JRST NTISER
NTIS1A:	SKIPGE NTOINP			; no output if still output reset
	 JRST NTISR3
	SKIPE ISLURP
	 JRST [	OUTCHR			; slurp mode can't buffer
		JRST NTISR3]		; since it can die at any time!
	SOSG TTOCTR			; buffer stuffed?
	 JRST [	OUTSTR TTOBFR
		MOVEI X,5*TTOBFL-1	; set up TTY buffer counter
		MOVEM X,TTOCTR
		MOVE X,[440700,,TTOBFR]	; set up TTY buffer pointer
		MOVEM X,TTOPTR
		SETZM TTOBFR
		MOVE X,[TTOBFR,,TTOBFR+1]
		BLT X,TTOBFR+TTOBFL-1
		JRST .+1]
	IDPB TTOPTR
NTISR3:	SKIPL OUTFLP			; output file in progress?
	 JRST NTISER
	SOSG DSOBF+2
	 OUTPUT DSO,
	IDPB DSOBF+1
	JRST NTISER
SUBTTL Command dispatch

; Command dispatch table

CMCDSP:	REPEAT 40,[NTISER,,NTISER ? ]	; default to no-op

DEFINE CMDCHR CHR,CDISP,DISP
 LOC CMCDSP+"CHR-"@
 CDISP,,DISP
TERMIN

; Command dispatch table.  All routines are assumed to return via POPJ P,

; CMDCHR character,αβdispatch,βdispatch

CMDCHR @,DBUG,NDBUG			; MRC fooling around
CMDCHR A,ATTN,ATTN			; send ATTN
CMDCHR C,CLSCON,CLSCON			; close connection
CMDCHR D,CLSOFL,OPNOFL			; output file
CMDCHR E,RECHO,LECHO			; echo mode
CMDCHR F,APPEND,DAPPND			; append file
CMDCHR I,CLSIFL,OPNIFL			; input file
CMDCHR J,EOFF,EON			; echo diddle without telling host
CMDCHR L,ECHATM,LCHATM			; line editor diddle
CMDCHR Q,PUNT,PUNT			; exit
CMDCHR R,CLSIFL,OPNIFS			; open file in nice slow way
CMDCHR T,LTRANS,ETRANS			; transparent mode
CMDCHR X,ESCSET,ESCSET			; set escape character

LOC CMCDSP+40
SUBTTL Command service routines

; Send ATTN

ATTN:	SKIPE DEBUGP
	 OUTSTR [ASCIZ/⊗INS*
/]
	PUSHJ P,NETINS			; send INS
	TELCMD [201 200]
	POPJ P,

; Enter remote echo mode

RECHO:	SKIPE ECHOP
	 POPJ P,
	SETOM ECHOP
	TELCMD [204]
	POPJ P,

; Enter local echo mode

LECHO:	SKIPN ECHOP
	 POPJ P,
	SETZM ECHOP
	TELCMD [203]
	POPJ P,
; More commands

; Echo diddle without asking host

EOFF:	SETOM ECHOP ? POPJ P,
EON:	SETZM ECHOP ? POPJ P,

; Enter character-at-a-time mode

ECHATM:	SETOM CHARMP
	HRROI [001000,,(SPCBRK)]
	TTYSET				; enter special activation mode
	POPJ P,

; Leave character-at-a-time mode

LCHATM:	SETZM CHARMP
	HRROI [002000,,(SPCBRK)]
	TTYSET				; leave special activation mode
	POPJ P,

; Close connection

CLSCON:	PUSHJ P,CLOSER

; Go away

PUNT:	MOVE [-2,,[012000,,10 ? 004000,,"P]]
	SKIPE TRANSP
	 TTYSET				; leave image mode and do [ESCAPE]P
	EXIT

; Enter transparent mode

ETRANS:	SKIPE DPYP			; DD's and III's can't be transparent
	 SKIPE DMDPYP			; DM's can be transparent
	  CAIA
	   POPJ P,
	SETOM TRANSP
	HRROI [011000,,10]
	TTYSET				; enter image mode
	POPJ P,

; Leave transparent mode

LTRANS:	SKIPN TRANSP
	 POPJ P,
	SETZM TRANSP
	MOVE [-2,,[012000,,10 ? 004000,,"P]]
	TTYSET				; leave image mode and do [ESCAPE]P
	POPJ P,

; Set escape character

ESCSET:	INCHRW ? ANDI 177 ? MOVEM ESCHAR ? POPJ P,

; MRC fooling around

DBUG:	SETOM DEBUGP ? POPJ P,
NDBUG:	SETZM DEBUGP ? POPJ P,
SUBTTL Append file

; Append to a file and always ask

APPEND:	SKIPGE OUTFLP			; file open?
	 JRST [	OUTSTR [ASCIZ/Output file already open!
/]
		POPJ P,]
	OUTSTR [ASCIZ/Append file name: /]
	PUSHJ P,GETFSP			; get filespec
	SKIPN X,FSPBLK
	 POPJ P,
	MOVEM X,OUTFLN
	MOVE FSPBLK+1 ? MOVEM OUTEXT
	MOVE FSPBLK+3 ? MOVEM OUTPPN
	LOOKUP DSO,FSPBLK
	 JRST [	OUTSTR [ASCIZ/LOOKUP failed!
/]
		SETZM OUTFLN		; toss away default
		POPJ P,]
	MOVE X,OUTPPN
	MOVEM X,FSPBLK+3
	ENTER DSO,FSPBLK
	 JRST [	OUTSTR [ASCIZ/ENTER failed!
/]
		POPJ P,]
	UGETF DSO,			; start appending
	SETOM OUTFLP
	POPJ P,

; Append but try using defaults

DAPPND:	SKIPGE OUTFLP			; file open?
	 JRST [	OUTSTR [ASCIZ/Output file already open!
/]
		POPJ P,]
	SKIPN X,OUTFLN
	 JRST APPEND
	MOVEM X,FSPBLK
	MOVE X,OUTEXT
	MOVEM X,FSPBLK+1
	SETZM FSPBLK+2
	MOVE X,OUTPPN
	MOVEM X,FSPBLK+3
	LOOKUP DSO,FSPBLK
	 JRST [	OUTSTR [ASCIZ/LOOKUP failed!
/]
		SETZM OUTFLN		; toss away default
		POPJ P,]
	MOVE X,OUTPPN
	MOVEM X,FSPBLK+3
	ENTER DSO,FSPBLK
	 JRST [	OUTSTR [ASCIZ/ENTER failed!
/]
		POPJ P,]
	UGETF DSO,			; start appending
	SETOM OUTFLP
	OUTSTR [ASCIZ/Appending to file /]
	MOVE X,OUTFLN
	PUSHJ P,OUTSIX
	OUTCHR [".]
	MOVE X,OUTEXT
	PUSHJ P,OUTSIX
	OUTCHR ["[]	;]
	HLLZ X,OUTPPN
	PUSHJ P,OUTSIX
	OUTCHR [",]
	HRLZ X,OUTPPN
	PUSHJ P,OUTSIX
	OUTSTR [ASCIZ/]
/]
	POPJ P,
SUBTTL Output file

; Close output file

CLSOFL:	AOSE OUTFLP			; file open?
	 POPJ P,
	CLOSE DSO,			; close output
	OUTSTR [ASCIZ/Output file /]
	MOVE X,OUTFLN
	PUSHJ P,OUTSIX
	OUTCHR [".]
	MOVE X,OUTEXT
	PUSHJ P,OUTSIX
	OUTCHR ["[]	;]
	HLLZ X,OUTPPN
	PUSHJ P,OUTSIX
	OUTCHR [",]
	HRLZ X,OUTPPN
	PUSHJ P,OUTSIX
	OUTSTR [ASCIZ/] closed.
/]
	POPJ P,

; Open output file

OPNOFL:	SKIPGE OUTFLP			; file open?
	 JRST [	OUTSTR [ASCIZ/Output file already open!
/]
		POPJ P,]
	OUTSTR [ASCIZ/Output file name: /]
	PUSHJ P,GETFSP			; get filespec
	SKIPN X,FSPBLK
	 POPJ P,
	MOVEM X,OUTFLN
	MOVE FSPBLK+1 ? MOVEM OUTEXT
	MOVE FSPBLK+3 ? MOVEM OUTPPN
	ENTER DSO,FSPBLK
	 JRST [	OUTSTR [ASCIZ/ENTER failed!
/]
		POPJ P,]
	SETOM OUTFLP
	POPJ P,
SUBTTL Input file

; Close input file

CLSIFL:	AOSE INPFLP			; file open?
	 POPJ P,
	CLOSE DSI,			; close input
	OUTSTR [ASCIZ/Input file /]
	MOVE X,INPFLN
	PUSHJ P,OUTSIX
	OUTCHR [".]
	MOVE X,INPEXT
	PUSHJ P,OUTSIX
	OUTCHR ["[]	;]
	HLLZ X,INPPPN
	PUSHJ P,OUTSIX
	OUTCHR [",]
	HRLZ X,INPPPN
	PUSHJ P,OUTSIX
	OUTSTR [ASCIZ/] closed.
/]
	SETZM SLOWFP
	POPJ P,

; Open input file

OPNIFS:	SETOM SLOWFP
OPNIFL:	SKIPGE INPFLP			; file open?
	 JRST [	OUTSTR [ASCIZ/Input file already open!
/]
		POPJ P,]
	OUTSTR [ASCIZ/Input file name: /]
	PUSHJ P,GETFSP			; get filespec
	SKIPN X,FSPBLK
	 POPJ P,
	MOVEM X,INPFLN
	MOVE FSPBLK+1 ? MOVEM INPEXT
	MOVE FSPBLK+3 ? MOVEM INPPPN
	LOOKUP DSI,FSPBLK
	 JRST [	OUTSTR [ASCIZ/LOOKUP failed!
/]
		SETZM SLOWFP
		POPJ P,]
	SETOM INPFLP
	POPJ P,
SUBTTL DDT bopper

DDTCAL:	SKIPN JOBDDT
	 POPJ P,			; no DDT!
	OUTSTR [ASCIZ/You're in DDT.
/]
	HRROI [002000,,(SPCBRK)]
	SKIPE CHARMP
	 TTYSET				; leave special activation mode
	PTJOBX [0 ? 4]
	PUSHJ P,@JOBDDT			; enter DDT
	PTJOBX [0 ? 3]
	HRROI [001000,,(SPCBRK)]
	SKIPE CHARMP
	 TTYSET				; enter special activation mode
	POPJ P,
SUBTTL Filespec input

; Smashes X, Y, and Z; sets up FSPBLK.

GETFSP:	HRROI [002000,,(SPCBRK)]
	SKIPE CHARMP
	 TTYSET				; leave special activation mode
	HRROI [012000,,10]
	SKIPE TRANSP
	 TTYSET				; leave image mode
	PTJOBX [0 ? 4]			; echo filespec
	SETZM FSPBLK ? SETZM FSPBLK+1 ? SETZM FSPBLK+2
	SETZ X,
	DSKPPN X,
	MOVEM X,FSPBLK+3
	PUSHJ P,GETSIX			; get file name
	JUMPE X,FSPLUZ
	MOVEM X,FSPBLK			; got file name
	CAIE Y,".
	 JRST NOEXT
	PUSHJ P,GETSIX			; try for extension
	MOVEM X,FSPBLK+1
NOEXT:	CAIN Y,↑J
	 JRST FSPDUN
	CAIE Y,"[			; must be a PPN
	 JRST FSPLUZ
	PUSHJ P,GETSIX
	TRNE X,-1
	 JRST FSPLUZ
	TLNN X,77
	 JUMPN X,[LSH X,-6 ? JRST .-1]
	SKIPE X
	 HLLM X,FSPBLK+3
	CAIE Y,",
	 JRST FSPEOS
	PUSHJ P,GETSIX
	TRNE X,-1
	 JRST FSPLUZ
	TLNN X,77
	 JUMPN X,[LSH X,-6 ? JRST .-1]
	SKIPE X
	 HLRM X,FSPBLK+3
FSPEOS:	CAIN Y,"]
FSPCCR:	 INCHWL Y
	ANDI Y,177
	CAIN Y,↑M
	 JRST FSPCCR
	CAIE Y,↑J
	 JRST FSPLUZ
FSPDUN:	PTJOBX [0 ? 3]
	HRROI [001000,,(SPCBRK)]
	SKIPE CHARMP
	 TTYSET				; enter special activation mode
	HRROI [011000,,10]
	SKIPE TRANSP
	 TTYSET				; enter image mode
	POPJ P,

FSPLUZ:	CLRBFI
	CAIN Y,175
	 JRST [	SETZM FSPBLK		; sorry defaulters
		OUTSTR [ASCIZ/ Aborted.
/]
		JRST FSPDUN]
	OUTSTR [ASCIZ/Invalid file specification.  Try again: /]
	JRST GETFSP
SUBTTL Sixbit & numeric TTY I/O

; Sixbit output routine.  Takes a word in X, smashes Y, flushes spaces.

OUTSIX:	SETZ Y,
	ROTC X,6
	JUMPE Y,OUTSX1
	ADDI Y,"A-'A
	OUTCHR Y
OUTSX1:	JUMPN X,OUTSIX
	POPJ P,


; Sixbit input routine.  Inputs a sixbit word in X, smashes Y and Z.

GETSIX:	SETZ X,
	MOVE Z,[440600,,X]
GETSX1:	INCHWL Y
	ANDI Y,177
	CAIN Y,↑M
	 JRST GETSX1
	CAIL Y,"a			; convert to upper case
	 CAILE Y,"z
	  CAIA
	   SUBI Y,"a-"A
	CAIL Y,"0			; only allow alphanumerics
	 CAILE Y,"Z
	  POPJ P,
	CAILE Y,"9
	 CAIL Y,"A
	  CAIA
	   POPJ P,
	SUBI Y,"A-'A			; convert to sixbit
	TRNN X,77			; don't go beyond last byte
	 IDPB Y,Z
	JRST GETSX1


...LIT:	CONSTANTS

END RSEXEC